package io.gitee.caoxiaoyu97.messageconvert.server.service;

import freemarker.template.TemplateException;
import io.gitee.caoxiaoyu97.messageconvert.common.CxyCloudTemplateUtils;
import io.gitee.caoxiaoyu97.messageconvert.exception.CxyException;
import io.gitee.caoxiaoyu97.messageconvert.server.CxyCloudGateWayServerUtil;
import io.gitee.caoxiaoyu97.messageconvert.server.ext.CxyCloudGateWayConvertProcessor;
import io.gitee.caoxiaoyu97.messageconvert.util.MessageUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/*********************************************************
 * 文件名称：CxyCloudServerServiceUtil.java
 * 系统名称：CXY自定义系统
 * 模块名称：io.gitee.caoxiaoyu97.messageconvert.server
 * 功能说明：对外提供服务的工具类
 * 开发人员 @author：caoxy31978
 * 开发时间 @date：2023/7/7 11:02
 * 修改记录：程序版本  修改日期  修改人员  修改单号  修改说明
 *********************************************************/
@Slf4j
public class CxyCloudGateWayServiceUtil {

    public static String invokeService(String outCode, String req) {
        CxyCloudGateWayServiceMetadata gateWayServerMetadata = CxyCloudGateWayServerUtil.getGateWayServerMetadata(outCode);
        try {
            return invokeServiceHandle(gateWayServerMetadata, req);
        } catch (TemplateException e) {
            throw new CxyException("9900", "模板渲染异常", e);
        } catch (IOException e) {
            throw new CxyException("9900", "模板加载异常", e);
        }
    }

    private static String invokeServiceHandle(CxyCloudGateWayServiceMetadata gateWayServerMetadata,
                                              String sourceReq) throws
            TemplateException, IOException {
        Map<String, Object> extMap = new HashMap<>();
        /*
          此时拥有的数据为，模板信息，原始req报文，ext贯穿对象
         */
        String targetRequest = converRequest(gateWayServerMetadata, sourceReq, extMap);
        /*
          此时拥有的数据为，模板信息，原始req报文，ext贯穿对象，req转换后报文
         */
        String sourceResponse = getResponse(gateWayServerMetadata, sourceReq, extMap, targetRequest);
        /*
          此时拥有的数据为，模板信息，原始req报文，ext贯穿对象，req转换后报文,原始resp报文
         */
        return converResponse(gateWayServerMetadata, sourceReq, extMap, targetRequest, sourceResponse);
    }

    private static String converResponse(CxyCloudGateWayServiceMetadata gateWayServerMetadata, String sourceReq,
                                         Map<String, Object> extMap, String targetRequest, String sourceResponse) throws
            IOException, TemplateException {
        HashMap<String, Object> respParam = new HashMap<>();
        respParam.put("sourceReq", MessageUtils.messageToMap(sourceReq));
        respParam.put("ext", extMap);
        respParam.put("targetReq", MessageUtils.messageToMap(targetRequest));
        respParam.put("resp", MessageUtils.messageToMap(sourceResponse));
        doBeforeRespProcessor(gateWayServerMetadata, sourceResponse, extMap);
        return CxyCloudTemplateUtils.convert(gateWayServerMetadata.getTempGroup(), gateWayServerMetadata.getRespTempName(), respParam);
    }

    private static void doBeforeRespProcessor(CxyCloudGateWayServiceMetadata gateWayServerMetadata,
                                              String sourceResponse, Map<String, Object> extMap) {
        List<CxyCloudGateWayConvertProcessor> processorList = gateWayServerMetadata.getProcessorList();
        if (processorList != null && processorList.size() > 0) {
            Map<String, Object> sourceRespMap = Collections.unmodifiableMap(MessageUtils.messageToMap(sourceResponse));
            for (CxyCloudGateWayConvertProcessor processor : processorList) {
                processor.beforeRespProcessor(sourceResponse, sourceRespMap, extMap);
            }
        }
    }

    private static String getResponse(CxyCloudGateWayServiceMetadata gateWayServerMetadata,
                                      String sourceReq,
                                      Map<String, Object> extMap, String targetRequest) throws IOException,
            TemplateException {
        String response;
        if (gateWayServerMetadata.isMock()) {
            HashMap<String, Object> mockParam = new HashMap<>();
            mockParam.put("sourceReq", MessageUtils.messageToMap(sourceReq));
            mockParam.put("ext", extMap);
            mockParam.put("req", MessageUtils.messageToMap(targetRequest));
            response = CxyCloudTemplateUtils.convert(gateWayServerMetadata.getTempGroup(), gateWayServerMetadata.getMockTempName(), mockParam);
        } else {
            CxyCloudGateWayService service = CxyCloudGateWayServerUtil.getGateWayService(gateWayServerMetadata.getInServiceBeanName());
            response = service.doServiceImpl(gateWayServerMetadata.getInCode(), targetRequest,extMap);
        }
        return response;
    }

    private static String converRequest(CxyCloudGateWayServiceMetadata gateWayServerMetadata,
                                        String sourceReq,
                                        Map<String, Object> extMap) throws
            TemplateException, IOException {
        Map<String, Object> requestParam = new HashMap<>();
        requestParam.put("req", MessageUtils.messageToMap(sourceReq));
        requestParam.put("ext", extMap);
        doBeforeReqProcessor(gateWayServerMetadata, sourceReq, extMap);
        return CxyCloudTemplateUtils.convert(gateWayServerMetadata.getTempGroup(), gateWayServerMetadata.getReqTempName(), requestParam);
    }

    private static void doBeforeReqProcessor(CxyCloudGateWayServiceMetadata gateWayServerMetadata, String sourceReq,
                                             Map<String, Object> extMap) {
        List<CxyCloudGateWayConvertProcessor> processorList = gateWayServerMetadata.getProcessorList();
        if (processorList != null && processorList.size() > 0) {
            Map<String, Object> sourceReqMap = Collections.unmodifiableMap(MessageUtils.messageToMap(sourceReq));
            for (CxyCloudGateWayConvertProcessor processor : processorList) {
                processor.beforeReqProcessor(sourceReq, sourceReqMap, extMap);
            }
        }
    }
}
